using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

namespace Nirvana
{
    public class BigWorld : MonoBehaviour
    {
        public SceneData SceneData => _sceneData;
        public bool IsDrawGizmos = false;
        public LayerMask ExcludeLayerMask;
        public string fileName;

        public delegate string GetResPath(int index);

        /// <summary>
        /// 玩家的Transform
        /// </summary>
        private Transform _player;

        /// <summary>
        /// 场景数据
        /// </summary>
        private SceneData _sceneData;

        private bool _isStart;

        /// <summary>
        /// 相机上一次计算时的问题
        /// </summary>
        private Vector3 _lastCameraPos = new Vector3(100000, 100000, 100000);

        /// <summary>
        /// 相机
        /// </summary>
        private Camera _mainCamera;

        /// <summary>
        /// 相机的Transform
        /// </summary>
        private Transform _mainCameraTransform;

        private RuntimeMeshBlocks _meshBlocks = new RuntimeMeshBlocks();

        private static bool _isUpdate;

        private void Start()
        {
            _isUpdate = true;
        }

        private void Update()
        {
            CalcObjects();
        }

        /// <summary>
        /// 设置玩家位置
        /// </summary>
        /// <param name="player"></param>
        public void SetPlayer(Transform player)
        {
            _player = player;
            _isStart = true;
            _mainCamera = Camera.main;
            _mainCameraTransform = _mainCamera.transform;
            CalcObjects();
        }

        /// <summary>
        /// 计算场景中物件与玩家的位置
        /// </summary>
        private void CalcObjects()
        {
            if (!_isStart || !_isUpdate || _mainCameraTransform == null || _player == null || _sceneData == null)
            {
                return;
            }

            Vector3 cameraPos = _mainCameraTransform.position;
            float offsetDistance = (_lastCameraPos - cameraPos).sqrMagnitude;
            Vector3 playerPos = _player.position;
            _meshBlocks.Update(ref playerPos, offsetDistance);
            if (offsetDistance > BigWorldHelper.Small)
            {
                _lastCameraPos = cameraPos;
            }

            LoadHelper.Update(Time.deltaTime);
        }

        /// <summary>
        /// 场景加载
        /// </summary>
        /// <param name="data"></param>
        public void Load(SceneData data)
        {
            _sceneData = data;
            for (int i = 0; i < data.Objects.Length; i++)
            {
                SerializedGameObject obj = data.Objects[i];
                Transform node = null;
                Transform parent = transform;
                if (obj.Type != ObjectType.Prefab && obj.Type != ObjectType.DynamicPrefab)
                {
                    node = new GameObject(obj.Name).transform;
                }

                if (obj.ParentId >= 0)
                {
                    if (obj.ParentId < data.Objects.Length)
                    {
                        parent = data.Objects[obj.ParentId].Node;
                    }
                    else
                    {
                        Debug.LogError("未找到父节点,请重新导出数据  " + name);
                    }
                }

                obj.Init(parent, node, GetResourcePath);
            }

            _meshBlocks.Init(data.SmallBlocks, data.SmallMeshBlockOffset, BigWorldHelper.MeshBlockRange, BigWorldHelper.MeshBlockCount);
        }

        private string GetResourcePath(int index)
        {
            if (_sceneData == null) return string.Empty;
            if (_sceneData.ResourcePaths == null) return string.Empty;
            if (index >= 0 && index < _sceneData.ResourcePaths.Length)
            {
                return _sceneData.ResourcePaths[index];
            }

            return string.Empty;
        }

        /// <summary>
        /// 清理数据
        /// </summary>
        public void Clear()
        {
            _mainCamera = null;
            _mainCameraTransform = null;
            _isStart = false;
            _isUpdate = false;
            _meshBlocks.UnInit();
        }
    }
}